package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcYingShiChannelMapper;
import com.csun.cmny.provider.device.yingshi.YingShiUtils;
import com.csun.cmny.provider.device.yingshi.entity.YingShiDeviceCameraVo;
import com.csun.cmny.provider.device.yingshi.entity.YingShiUrlVo;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.yingshi.YingShiChannelDto;
import com.csun.cmny.provider.model.dto.yingshi.YingShiChannelQueryDto;
import com.csun.cmny.provider.model.dto.yingshi.YingShiPlayerDto;
import com.csun.cmny.provider.model.enums.device.DeviceStatusEnum;
import com.csun.cmny.provider.model.vo.yingshi.YingShiChannelVo;
import com.csun.cmny.provider.model.vo.yingshi.YingShiMonitorVo;
import com.csun.cmny.provider.model.vo.yingshi.YingShiPlayerVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.DateUtil;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2021/8/27 16:47
 * @Description: 萤石摄像头通道应用实现
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcYingShiChannelServiceImpl extends BaseService<DmcYingShiChannel>
        implements DmcYingShiChannelService {

    @Resource
    private YingShiUtils yingShiUtils;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcYingShiChannelMapper dmcYingShiChannelMapper;
    @Resource
    private DmcYingShiCameraService dmcYingShiCameraService;
    @Resource
    private DmcYingShiConfigService dmcYingShiConfigService;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private DmcYingShiMonitorService dmcYingShiMonitorService;

    /**
     * 获取播放地址
     *
     * @param id  the ying shi channel id
     *
     * @return  the ying shi player vo
     */
    @Override
    public YingShiPlayerVo getPlayUrl(Long id) {

        DmcYingShiChannel dmcYingShiChannel = dmcYingShiChannelMapper.selectByPrimaryKey(id);
        if (PublicUtil.isEmpty(dmcYingShiChannel)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622012);
        }

        // 校验摄像头id
        DmcYingShiCamera dmcYingShiCamera = dmcYingShiCameraService.selectByKey(dmcYingShiChannel.getDeviceId());
        if (PublicUtil.isEmpty(dmcYingShiCamera)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622007);
        }
        DmcDevice dmcDevice = dmcDeviceService.selectByKey(dmcYingShiChannel.getDeviceId());
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622007);
        }

        // 获取token
        DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(dmcDevice.getGroupId());
        if (PublicUtil.isEmpty(dmcYingShiConfig)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622009);
        }

        YingShiPlayerDto yingShiPlayerDto = new YingShiPlayerDto();
        yingShiPlayerDto.setAccessToken(dmcYingShiConfig.getAccessToken());
        yingShiPlayerDto.setChannelNo(dmcYingShiChannel.getChannelNo());
        yingShiPlayerDto.setDeviceSerial(dmcDevice.getDeviceNo());

        YingShiUrlVo yingShiUrlVo = yingShiUtils.getPlayUrl(yingShiPlayerDto);

        YingShiPlayerVo yingShiPlayerVo = new YingShiPlayerVo();
        yingShiPlayerVo.setAccessToken(dmcYingShiConfig.getAccessToken());
        yingShiPlayerVo.setCode(dmcYingShiCamera.getCode());
        yingShiPlayerVo.setUrl(yingShiUrlVo.getUrl());
        if (PublicUtil.isNotEmpty(yingShiUrlVo.getExpireTime())) {
            yingShiPlayerVo.setExpireTime(DateUtil.dateToString(new Date(yingShiUrlVo.getExpireTime())));
        }

        return yingShiPlayerVo;
    }

    /**
     * 查询萤石摄像头通道列表 - 分页
     *
     * @param yingShiChannelQueryDto    the ying shi channel query dto
     *
     * @return  the ying shi channel vo list.
     */
    @Override
    public List<YingShiChannelVo> queryListWithPage(YingShiChannelQueryDto yingShiChannelQueryDto) {

        PageHelper.startPage(yingShiChannelQueryDto.getPageNum(), yingShiChannelQueryDto.getPageSize());

        List<YingShiChannelVo> yingShiChannelVoList = dmcYingShiChannelMapper.queryListWithPage(yingShiChannelQueryDto);

        // 查询通道状态
        if (PublicUtil.isNotEmpty(yingShiChannelVoList)) {
            // 获取token
            DmcDevice dmcDevice = dmcDeviceService.selectByKey(yingShiChannelQueryDto.getDeviceId());
            if (PublicUtil.isEmpty(dmcDevice)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622007);
            }

            DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(dmcDevice.getGroupId());
            if (PublicUtil.isEmpty(dmcYingShiConfig)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622009);
            }

            List<YingShiDeviceCameraVo> yingShiDeviceCameraVoList = yingShiUtils
                    .getDeviceCameraList(dmcYingShiConfig.getAccessToken(), dmcDevice.getDeviceNo());
            if (PublicUtil.isNotEmpty(yingShiDeviceCameraVoList)) {
                Map<Integer, YingShiDeviceCameraVo> yingShiDeviceCameraVoMap =
                        yingShiDeviceCameraVoList.stream().collect(Collectors.toMap(YingShiDeviceCameraVo::getChannelNo, a -> a, (k1, k2) -> k1));

                for (YingShiChannelVo yscv : yingShiChannelVoList) {
                    yscv.setStatus(DeviceStatusEnum.OFFLINE.getKey());
                    YingShiDeviceCameraVo vo = yingShiDeviceCameraVoMap.get(yscv.getChannelNo());
                    if (PublicUtil.isNotEmpty(vo) && vo.getStatus().equals(1)) {    // 在线
                        yscv.setStatus(DeviceStatusEnum.ONLINE.getKey());
                    }
                }
            }

        }

        return yingShiChannelVoList;
    }

    /**
     * 添加萤石摄像头通道信息
     *
     * @param yingShiChannelDto the ying shi channel dto
     * @param loginAuthDto      the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer save(YingShiChannelDto yingShiChannelDto, LoginAuthDto loginAuthDto) {

        DmcYingShiChannel dmcYingShiChannel = new DmcYingShiChannel();
        BeanUtils.copyProperties(yingShiChannelDto, dmcYingShiChannel);

        // 校验摄像头id
        DmcYingShiCamera dmcYingShiCamera = dmcYingShiCameraService.selectByKey(yingShiChannelDto.getDeviceId());
        if (PublicUtil.isEmpty(dmcYingShiCamera)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622007);
        }
        DmcDevice dmcDevice = dmcDeviceService.selectByKey(yingShiChannelDto.getDeviceId());
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622007);
        }

        // 校验通道是否已经存在
        if (!checkChannelNo(null, yingShiChannelDto.getDeviceId(), yingShiChannelDto.getChannelNo())) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622010);
        }

        // 校验摄像头通道
        // 获取token
        DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(loginAuthDto.getGroupId());
        if (PublicUtil.isEmpty(dmcYingShiConfig)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622009);
        }
        List<YingShiDeviceCameraVo> yingShiDeviceCameraVoList = yingShiUtils
                .getDeviceCameraList(dmcYingShiConfig.getAccessToken(), dmcDevice.getDeviceNo());
        boolean flag = true;
        for (YingShiDeviceCameraVo vo : yingShiDeviceCameraVoList) {
            if (vo.getChannelNo().equals(yingShiChannelDto.getChannelNo())) {
                flag = false;
                break;
            }
        }
        if (flag) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622011);
        }

        dmcYingShiChannel.setUpdateInfo(loginAuthDto);

        return dmcYingShiChannelMapper.insertSelective(dmcYingShiChannel);
    }

    /**
     * 修改萤石摄像头通道信息
     *
     * @param yingShiChannelDto the ying shi channel query dto
     * @param loginAuthDto      the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer edit(YingShiChannelDto yingShiChannelDto, LoginAuthDto loginAuthDto) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(yingShiChannelDto.getId()),
                cmnyMessageSource.getMessage("ying.shi.channel.id.null", null));

        // 校验是否存在
        DmcYingShiChannel dmcYingShiChannel = dmcYingShiChannelMapper.selectByPrimaryKey(yingShiChannelDto.getId());
        if (PublicUtil.isEmpty(dmcYingShiChannel)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622006);
        }

        if (PublicUtil.isNotEmpty(yingShiChannelDto.getChannelNo())) {
            // 校验通道是否已经存在
            if (!checkChannelNo(yingShiChannelDto.getId(), yingShiChannelDto.getDeviceId(), yingShiChannelDto.getChannelNo())) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622010);
            }

            // 校验摄像头通道
            DmcDevice dmcDevice = dmcDeviceService.selectByKey(dmcYingShiChannel.getDeviceId());
            if (PublicUtil.isEmpty(dmcDevice)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622007);
            }
            // 获取token
            DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(loginAuthDto.getGroupId());
            if (PublicUtil.isEmpty(dmcYingShiConfig)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622009);
            }
            List<YingShiDeviceCameraVo> yingShiDeviceCameraVoList = yingShiUtils
                    .getDeviceCameraList(dmcYingShiConfig.getAccessToken(), dmcDevice.getDeviceNo());
            boolean flag = true;
            for (YingShiDeviceCameraVo vo : yingShiDeviceCameraVoList) {
                if (vo.getChannelNo().equals(yingShiChannelDto.getChannelNo())) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622011);
            }

            dmcYingShiChannel.setChannelNo(yingShiChannelDto.getChannelNo());
        }

        if (PublicUtil.isNotEmpty(yingShiChannelDto.getChannelName())) {
            dmcYingShiChannel.setChannelName(yingShiChannelDto.getChannelName());
        }
        if (PublicUtil.isNotEmpty(yingShiChannelDto.getChannelLocation())) {
            dmcYingShiChannel.setChannelLocation(yingShiChannelDto.getChannelLocation());
        }

        dmcYingShiChannel.setUpdateInfo(loginAuthDto);

        return dmcYingShiChannelMapper.updateByPrimaryKeySelective(dmcYingShiChannel);
    }

    /**
     * 根据id删除萤石摄像头通道信息
     *
     * @param id    the ying shi camera channel id
     *
     * @return  the int.
     */
    @Override
    public Integer deleteById(Long id) {

        // 查询是否已经存在
        DmcYingShiMonitor dmcYingShiMonitor = dmcYingShiMonitorService.selectByKey(id);
        if (PublicUtil.isNotEmpty(dmcYingShiMonitor)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622013);
        }

        return dmcYingShiChannelMapper.deleteByPrimaryKey(id);
    }

    /**
     * 校验通道号是否存在
     *
     * @param id    the id
     * @param deviceId  the device id
     * @param channelNo the channel no
     *
     * @return  the boolean true-不存在 false-存在
     */
    @Override
    public boolean checkChannelNo(Long id, Long deviceId, Integer channelNo) {

        Example example = new Example(DmcYingShiChannel.class);
        Example.Criteria criteria = example.createCriteria();

        if (id != null) {
            criteria.andNotEqualTo("id", id);
        }

        criteria.andEqualTo("deviceId", deviceId);
        criteria.andEqualTo("channelNo", channelNo);

        int result = selectCountByExample(example);

        return result < 1;
    }

    /**
     * 根据通道id获取通道信息
     *
     * @param channelId the channel id
     *
     * @return  the ying shi monitor vo
     */
    @Override
    public YingShiMonitorVo selectByChannelId(Long channelId) {

        return dmcYingShiChannelMapper.selectByChannelId(channelId);
    }
    //查询萤石通道号
    @Override
    public List<DmcYingShiChannel> selectChannelById(Long id) {
        return dmcYingShiChannelMapper.selectChannelById(id);
    }
}
